#include "panel.h"
#include "memchunk.h"
#include <pthread.h>
#include <curl/curl.h>
#include <time.h>
#include <stdio.h>
#include <cjson/cJSON.h>

#define GAODE_KEY "543b7b6c08e25803d4adf379f2b68d50"

typedef struct
{
    char weather[32];
    char temperature[32];
    char humidity[32];
    char wind_direction[32];
    char wind_speed[32];
    pthread_mutex_t data_lock;
} WeatherData;

lv_obj_t *time_label;
lv_obj_t *date_label;
lv_obj_t *weather_label;
lv_obj_t *temperature_label;
lv_obj_t *humidity_label;
lv_obj_t *wind_label;

static size_t memchunk_write(void *ptr, size_t size, size_t n, void *user_p)
{
    MemChunk *chunk = user_p;
    return memchunk_append(chunk, ptr, size * n);
}

static int url_get(char *url, MemChunk *chunk)
{
    long return_code;
    CURL *curl = curl_easy_init();

    if (!curl)
    {
        return -1;
    }

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memchunk_write);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, chunk);

    if (curl_easy_perform(curl) != CURLE_OK)
    {
        curl_easy_cleanup(curl);
        return -1;
    }

    // 请求成功，查看返回码
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &return_code);
    curl_easy_cleanup(curl);
    return return_code == 200 ? 0 : -1;
}

static int parse_city(char *json, char *city)
{
    cJSON *json_obj = cJSON_Parse(json);
    if (json_obj == NULL)
    {
        return -1;
    }
    cJSON *adcode = cJSON_GetObjectItem(json_obj, "adcode");
    if (adcode == NULL || !cJSON_IsString(adcode))
    {
        cJSON_Delete(json_obj);
        return -1;
    }
    strcpy(city, adcode->valuestring);
    cJSON_Delete(json_obj);
    return 0;
}
static int parse_weather(char *json, WeatherData *data)
{
    cJSON *json_obj = cJSON_Parse(json);
    if (json_obj == NULL)
    {
        return -1;
    }

    cJSON *lives = cJSON_GetObjectItem(json_obj, "lives");
    if (lives == NULL || !cJSON_IsArray(lives))
    {
        cJSON_Delete(json_obj);
        return -1;
    }

    cJSON *live = cJSON_GetArrayItem(lives, 0);
    if (live == NULL)
    {
        cJSON_Delete(json_obj);
        return -1;
    }

    cJSON *weather = cJSON_GetObjectItem(live, "weather");
    cJSON *temperature = cJSON_GetObjectItem(live, "temperature");
    cJSON *winddirection = cJSON_GetObjectItem(live, "winddirection");
    cJSON *windpower = cJSON_GetObjectItem(live, "windpower");
    cJSON *humidity = cJSON_GetObjectItem(live, "humidity");

    if (!weather || !temperature || !winddirection || !windpower || !humidity)
    {
        cJSON_Delete(json_obj);
        return -1;
    }

    if (!cJSON_IsString(weather) ||
        !cJSON_IsString(temperature) ||
        !cJSON_IsString(winddirection) ||
        !cJSON_IsString(windpower) ||
        !cJSON_IsString(humidity))
    {
        cJSON_Delete(json_obj);
        return -1;
    }
    pthread_mutex_lock(&data->data_lock);
    strcpy(data->weather, weather->valuestring);
    strcpy(data->temperature, temperature->valuestring);
    strcpy(data->wind_direction, winddirection->valuestring);
    strcpy(data->wind_speed, windpower->valuestring);
    strcpy(data->humidity, humidity->valuestring);
    pthread_mutex_unlock(&data->data_lock);
    cJSON_Delete(json_obj);
    return 0;
}

// 定时更新面板的信息，每秒钟调用一次
static void update_panel(lv_timer_t *timer)
{
    char time_str[32];
    char date_str[32];
    lv_obj_t *panel = timer->user_data;
    WeatherData *data = panel->user_data;

    time_t now = time(NULL);
    struct tm *time_info = localtime(&now);
    strftime(time_str, sizeof(time_str), "%H:%M:%S", time_info);
    strftime(date_str, sizeof(date_str), "%Y-%m-%d", time_info);

    lv_label_set_text(time_label, time_str);
    lv_label_set_text(date_label, date_str);

    pthread_mutex_lock(&data->data_lock);
    lv_label_set_text_fmt(weather_label, "当日天气: %s", data->weather);
    lv_label_set_text_fmt(temperature_label, "温度: %s", data->temperature);
    lv_label_set_text_fmt(humidity_label, "湿度: %s", data->humidity);
    lv_label_set_text_fmt(wind_label, "风向: %s, 风力: %s", data->wind_direction, data->wind_speed);
    pthread_mutex_unlock(&data->data_lock);
}

static void *weather_update_thread(void *data)
{
    char url[256];
    char adcode[7];
    WeatherData *weather_data = data;
    MemChunk chunk;

    // 首先请求城市信息，获取城市代码
    memset(&chunk, 0, sizeof(MemChunk));
    memchunk_init(&chunk);
    sprintf(url, "http://restapi.amap.com/v3/ip?key=%s", GAODE_KEY);
    if (url_get(url, &chunk) < 0)
    {
        memchunk_free(&chunk);
        return NULL;
    }

    if (parse_city(chunk.ptr, adcode) < 0)
    {
        memchunk_free(&chunk);
        return NULL;
    }

    // 按照adcode请求当前地址的天气
    memchunk_init(&chunk);
    sprintf(url, "http://restapi.amap.com/v3/weather/weatherInfo?key=%s&city=%s&extensions=base", GAODE_KEY, adcode);
    if (url_get(url, &chunk) < 0)
    {
        memchunk_free(&chunk);
        return NULL;
    }

    parse_weather(chunk.ptr, weather_data);
    memchunk_free(&chunk);
    return NULL;
}

// 定时联网更新天气，每分钟调用一次
static void update_weather(lv_timer_t *timer)
{
    pthread_t thread;
    lv_obj_t *panel = timer->user_data;
    if (pthread_create(&thread, NULL, weather_update_thread, panel->user_data) > 0)
    {
        pthread_detach(thread);
    }
}
lv_obj_t *panel_create()
{
    LV_FONT_DECLARE(lv_font_chinese_18);
    LV_IMG_DECLARE(background);
    lv_obj_t *panel = lv_obj_create(lv_scr_act());
    lv_obj_set_height(panel, 272);
    lv_obj_set_width(panel, 480);
    lv_obj_set_style_bg_img_src(panel, &background, LV_PART_MAIN);

    panel->user_data = lv_mem_alloc(sizeof(WeatherData));
    memset(panel->user_data, 0, sizeof(WeatherData));
    pthread_mutex_init(&((WeatherData *)panel->user_data)->data_lock, NULL);

    time_label = lv_label_create(panel);
    lv_obj_align(time_label, LV_ALIGN_CENTER, 0, -60);
    lv_obj_set_style_text_font(time_label, &lv_font_montserrat_48, 0);

    date_label = lv_label_create(panel);
    lv_obj_align(date_label, LV_ALIGN_CENTER, 0, -20);
    lv_obj_set_style_text_font(date_label, &lv_font_chinese_18, 0);

    weather_label = lv_label_create(panel);
    lv_obj_align(weather_label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_text_font(weather_label, &lv_font_chinese_18, 0);

    temperature_label = lv_label_create(panel);
    lv_obj_align(temperature_label, LV_ALIGN_CENTER, 0, 20);
    lv_obj_set_style_text_font(temperature_label, &lv_font_chinese_18, 0);

    wind_label = lv_label_create(panel);
    lv_obj_align(wind_label, LV_ALIGN_CENTER, 0, 40);
    lv_obj_set_style_text_font(wind_label, &lv_font_chinese_18, 0);

    humidity_label = lv_label_create(panel);
    lv_obj_align(humidity_label, LV_ALIGN_CENTER, 0, 60);
    lv_obj_set_style_text_font(humidity_label, &lv_font_chinese_18, 0);

    lv_timer_t *panel_updater = lv_timer_create(update_panel, 1000, panel);
    lv_timer_t *weather_updater = lv_timer_create(update_weather, 60000, panel);

    update_panel(panel_updater);
    update_weather(weather_updater);
    return panel;
}